﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace CharacterAnimationEditor
{
    public class KeyFrame
    {
        public float Time;
        public Skeleton Pose;

        public KeyFrame(Context context, float time)
        {
            Time = time;
            Pose = new Skeleton(context, new Vector2(0,0), "SkeletonRig.txt");
        }
    }

    class KeyFrameController
    {
        public void Update(Skeleton skeleton, KeyFrame kf1, KeyFrame kf2, float time)
        {
            time -= kf1.Time;
            time /= (kf2.Time - kf1.Time);

            InterplateSkeleton(skeleton, kf1.Pose, kf2.Pose, time);
        }

        public void InterplateSkeleton(Skeleton target, Skeleton sk1, Skeleton sk2, float time)
        {
            InterpolateBone(target.Body, sk1.Body, sk2.Body, time);
        }

        public void InterpolateBone(Bone targetBone, Bone bone1, Bone bone2, float time)
        {
            targetBone.LocalPosition = Vector2.Lerp(bone1.LocalPosition, bone2.LocalPosition, time);
            targetBone.LocalRotation = LerpAngle(bone1.LocalRotation, bone2.LocalRotation, time);

            for (int i = 0; i < targetBone.Children.Count; ++i)
            {
                InterpolateBone(
                    targetBone.Children[i],
                    bone1.Children[i],
                    bone2.Children[i],
                    time);
            }
        }


        public static float LerpAngle(float start, float end, float scale)
        {
            start = MathHelper.WrapAngle(start);
            end = MathHelper.WrapAngle(end);
            float delta = end - start;

            // If delta is not the shortest way, travel in the opposite direction  
            if (delta > MathHelper.Pi)
            {
                return (MathHelper.WrapAngle(start - (MathHelper.TwoPi - delta) * scale));
            }
            else if (delta < -MathHelper.Pi)
            {
                return (MathHelper.WrapAngle(start + (MathHelper.TwoPi + delta) * scale));
            }

            // No special case needed  
            return (start + delta * scale);
        }
    }
}
